package com.cooper.pagination;

import java.io.IOException;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.BodyTagSupport;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class PageNavigationTag extends BodyTagSupport{
	
	private static final long serialVersionUID = 8593397187099608181L;

	private Logger log = LoggerFactory.getLogger(this.getClass());
	
	public static final String DEFAULT_GOTO_PAGE_FUNCTION = "gotoPage";
	public static final String DEFAULT_PAGINATION_FORM = "paginationForm";
	
	private boolean showTotalSize = false;
	private String gotoFunction = DEFAULT_GOTO_PAGE_FUNCTION;
	private String url = null;
	private String formName = DEFAULT_PAGINATION_FORM;
	private String className = "pagination";
	private boolean showFirstAndLast = true;
	private PageInfo pageInfo = new PageInfo();
	
	@Override
	public int doStartTag() throws JspException {
		StringBuffer buffer = new StringBuffer();
		try {
			if(false == this.checkParam()){
				buffer.append("Pagination parsed error, please see log.");
				return EVAL_BODY_INCLUDE;
			}
			int totalPage = (pageInfo.getRowCount() - 1)/pageInfo.getPageSize() + 1;
			int startIndex = (pageInfo.getPageIndex()-1) * pageInfo.getPageSize();
			int endIndex = (pageInfo.getPageIndex() * pageInfo.getPageSize()) > pageInfo.getRowCount()? pageInfo.getRowCount(): pageInfo.getPageIndex()*pageInfo.getPageSize();
			
			if(pageInfo.getStartPage() == pageInfo.getEndPage()){
				
			} else if(0 < pageInfo.getRowCount()){
				buffer.append("<ul class='").append(this.className).append("'>");
				if(true == this.showFirstAndLast){
					if(1 == pageInfo.getPageIndex()){
						buffer.append("<li class='disabled'><a href='javascript:void(0)'>"+Caption.FIRST+"</a></li>");
					} else {
						buffer.append("<li><a href='javascript:").append(this.gotoFunction).append("(1);'>"+Caption.FIRST+"</a></li>");
					}
				}
				if(1 == pageInfo.getPageIndex()){
					buffer.append("<li class='disabled'><a href='javascript:void(0)'>")
						.append(this.showFirstAndLast?"&nbsp;":"&nbsp;").append(Caption.PREV+"</a></li>");
				} else {
					buffer.append("<li><a href='javascript:").append(this.gotoFunction).append("(")
						.append(pageInfo.getPageIndex()-1).append(");'>"+Caption.PREV)
						.append(this.showFirstAndLast?"&nbsp;":"&nbsp;").append("</a></li>");
				}
				
				for(long index= pageInfo.getStartPage(); index <= pageInfo.getEndPage(); index++){
					if(index == pageInfo.getPageIndex()){
						buffer.append("<li class='active'><a href='javascript:void(0);'>").append(index).append("</a></li>");
					} else {
						buffer.append("<li><a href='javascript:").append(gotoFunction).append("(")
						.append(index).append(");'>").append(index).append("</a></li>");
					}
				}
				
				if(totalPage == pageInfo.getPageIndex()){
					buffer.append("<li class='disabled'><a href='javascript:void(0)'>")
						.append(this.showFirstAndLast?"&nbsp;":"&nbsp;").append(Caption.NEXT+"</a></li>");
				} else {
					buffer.append("<li><a href='javascript:").append(gotoFunction).append("(")
						.append(pageInfo.getPageIndex()+1).append(");'>"+Caption.NEXT)
						.append(this.showFirstAndLast?"&nbsp;":"&nbsp;").append("</a></li>");
				}
				
				if(true == this.showFirstAndLast){
					if(totalPage == pageInfo.getPageIndex()){
						buffer.append("<li class='disabled'><a href='javascript:void(0)'>"+Caption.LAST+"</a></li>");
					} else {
						buffer.append("<li><a href='javascript:").append(gotoFunction).append("(")
							.append(totalPage).append(");'>"+Caption.LAST+"</a></li>");
					}
				}
				
				if(true == this.isShowTotalSize() && 0 < pageInfo.getRowCount()){
					buffer.append("<li class='disabled'><a>").append(startIndex+1)
						.append("-").append(endIndex).append("/")
						.append(pageInfo.getRowCount()).append("</a></li>");
				}
				buffer.append("</ul>");
			}
			
			pageContext.getOut().write(buffer.toString());
		} catch (IOException e) {
			log.error("Error:", e);
		}
		return EVAL_BODY_INCLUDE;
	}
	
	@Override
	public int doEndTag() throws JspException {
		StringBuffer buffer = new StringBuffer();
		if(DEFAULT_PAGINATION_FORM.equals(this.formName)){
			buffer.append("<form name='"+this.formName+"' action='").append(url).append("' method='GET'>");
			buffer.append("<input type='hidden' id='pageIndex' name='pageIndex' value='").append(this.pageInfo.getPageIndex()).append("'/>");
			buffer.append("</form>");
		} else {
			buffer.append("<input type='hidden' id='pageIndex' name='pageIndex' value='").append(this.pageInfo.getPageIndex()).append("'/>");
		}
		buffer.append(this.makeGotoFunction());
		try {
			pageContext.getOut().write(buffer.toString());
		} catch (IOException e) {
			log.error("Error:", e);
		}
		return EVAL_PAGE;
	}
	
	private StringBuffer makeGotoFunction(){
		StringBuffer buffer = new StringBuffer();
		buffer.append("<script type='text/javascript'>");
		buffer.append("function gotoPage(page){$('#pageIndex').val(page);");
		buffer.append("document.").append(this.formName).append(".submit();");
		buffer.append("}</script>");
		return buffer;
	}
	
	private boolean checkParam(){
		if(null == this.pageInfo){
			log.error("Can't find pagination expression name.");
			return false;
		}
		return true;
	}

	public String getGotoFunction() {
		return gotoFunction;
	}

	public void setGotoFunction(String gotoFunction) {
		this.gotoFunction = gotoFunction;
	}

	public String getUrl() {
		return url;
	}

	public void setUrl(String url) {
		this.url = url;
	}

	public String getFormName() {
		return formName;
	}

	public void setFormName(String formName) {
		this.formName = formName;
	}

	public PageInfo getPageInfo() {
		return pageInfo;
	}

	public void setPageInfo(PageInfo pageInfo) {
		this.pageInfo = pageInfo;
	}

	public boolean isShowTotalSize() {
		return showTotalSize;
	}

	public void setShowTotalSize(boolean showTotalSize) {
		this.showTotalSize = showTotalSize;
	}

	public String getClassName() {
		return className;
	}

	public void setClassName(String className) {
		this.className = className;
	}

	public boolean isShowFirstAndLast() {
		return showFirstAndLast;
	}

	public void setShowFirstAndLast(boolean showFirstAndLast) {
		this.showFirstAndLast = showFirstAndLast;
	}
	
	public static final class Caption {
		public static final String FIRST = "首页";
		public static final String PREV = "上一页";
		public static final String NEXT = "下一页";
		public static final String LAST = "末页";
	}
	
}
